<template>
  <div class="color-select">
    <el-select
      ref="colors"
      v-model="selectKey"
      value-key="key"
      :popper-class="popperClass"
      placeholder="*多种*"
      @change="onChange"
    >
      <el-option
        v-for="item in selectOptions"
        :key="item.key"
        :label="item.label"
        :value="item.key"
      >
        <color-item :value="item" />
      </el-option>
    </el-select>
    <el-color-picker
      v-model="pickColor"
      :predefine="predefineColors"
      :show-alpha="false"
      size="mini"
      @change="onColorPickerChange"
    />
  </div>
</template>

<script>
import ColorItem from './item'
import StyleConfig from '../../config/style'

export default {
  name: 'ColorSelect',
  components: {
    ColorItem
  },
  props: {
    value: {
      type: String,
      required: true
    },
    // ByLayer和ByBlock
    colors: {
      type: Array,
      // required: false,
      default: () => []
    }
  },
  data() {
    return {
      // select组件的value
      selectKey: undefined,
      // color-picker组件的value
      pickColor: '#FFFFFF',
      namedColors: [],
      // 命名颜色列表
      namedColorMap: {},
      // 标准颜色列表
      standardColors: [
        {
          // key: 'red',
          color: '#FF0000',
          label: '红'
        },
        {
          // key: 'yellow',
          color: '#FFFF00',
          label: '黄'
        },
        {
          // key: 'green',
          color: '#00FF00',
          label: '绿'
        },
        {
          // key: 'cyan',
          color: '#00FFFF',
          label: '青'
        },
        {
          // key: 'blue',
          color: '#0000FF',
          label: '蓝'
        },
        {
          // key: 'white',
          color: '#FFFFFF',
          label: '白'
        },
        {
          // key: 'black',
          color: '#000000',
          label: '黑'
        }
      ],
      // key与颜色数据之间的映射(内部使用)
      // 格式: { key: {value, label} }
      colorMap: {},
      // 颜色与key之间的反向映射(内部使用)
      // 格式: { value: key, }
      colorKeys: {},
      // 要显示的颜色列表(内部使用)
      // 格式: ['red', 'blue', ...]
      colorList: [],
      // popper
      popperClass: StyleConfig.Select.popperClass
    }
  },
  computed: {
    colorItem: function() {
      return this.getColorItem(this.selectKey)
    },
    // select组件参数: colors = [{ key: 'red', value:'#FF00000', label:'红' } ]
    selectOptions: function() {
      const datas = []
      const arr = [...this.namedColors, ...this.colorList]
      // console.log('selectOptions:', this.colorMap)
      arr.forEach(key => {
        const item = this.colorMap[key]
        if (item) {
          // console.log('--->options:', key, item)
          datas.push({
            key: key,
            color: item.color,
            label: item.label
          })
        }
      })
      return datas
    },
    // color-picker组件参数: predefineColors
    predefineColors: function() {
      const datas = []
      const that = this
      this.colorList.forEach(key => {
        // 命名颜色不添加到预定义颜色中
        if (!that.namedColorMap.hasOwnProperty(key)) {
          datas.push(that.colorMap[key].color)
        }
      })
      return datas
    }
  },
  watch: {
    colors(val) {
      this.updateByColors(val)
    },
    value(val) {
      if (val) {
        const _val = val.trim()
        if (!_val) {
          this.selectKey = undefined
        } else {
          if (this.namedColorMap.hasOwnProperty(_val)) {
            const key = _val
            // 初始化select组件的value
            this.selectKey = key
            // 初始化color-picker组件的value
            this.pickColor = this.getColor(key)
          } else {
            // 当前value是一个16进制颜色字符串,比如value='#FF0000'
            // 更新select组件
            this.updateSelect(_val)
          }
        }
      } else {
        this.selectKey = undefined
      }
    }
  },
  created() {
    // 初始化colorMap、colorKeys、colorList
    this.standardColors.forEach(item => {
      const { color, label } = item
      // 如果没有定义key字段,则使用color作为key
      let key = color
      if (item.hasOwnProperty('key')) {
        key = item.key
      }
      this.colorMap[key] = { color, label }
      this.colorKeys[color] = key
      this.colorList.push(key)
    })
    // console.log('color.vue created hook:', this.colors)
    // 初始化,如果父组件传递了colors数据,则更新颜色相关数据(colorMap、colorKeys、colors)
    this.updateByColors(this.colors)
  },
  methods: {
    // 获取key对应的颜色值(16进制字符串)
    getColor(key) {
      return this.colorMap[key].color
    },
    // 获取key对应的颜色参数(key、color、label)
    getColorItem(key) {
      // console.log('getColorItem:', this.colorMap, key)
      return {
        key: key,
        color: this.colorMap[key].color,
        label: this.colorMap[key].label
      }
    },
    isValidHexColor(color) {
      // 15个常用js正则表达式
      // https://www.cnblogs.com/myTerritory/p/6855932.html
      const HexColorPattern = /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/
      return HexColorPattern.test(color)
    },
    // 初始化(如果父组件通过props传入了options数据)
    updateByColors(options) {
      // console.log('updateByColors', options)
      this.namedColors = []
      options.forEach(item => {
        // console.log('item:', item)
        const { color, label } = item
        let key = color
        if (item.hasOwnProperty('key')) {
          key = item.key
        }
        // 如果key不是16进制颜色字符串,则认为该颜色是命名颜色
        if (!this.isValidHexColor(key)) {
          // if (!this.colorMap.hasOwnProperty(key)) {
          this.colorMap[key] = { color, label }
          // 记录命名颜色 -> key之间的映射
          this.namedColorMap[key] = color
          // 添加到colorList的前面
          this.namedColors.push(key)
          // }
        } else {
          if (!this.colorKeys.hasOwnProperty(color)) {
            // 用户新增的颜色(key == color)
            this.colorMap[key] = { color, label }
            this.colorKeys[color] = key
            // 添加到colorList的后面
            this.colorList.push(key)
          }
        }
      })
      // if (namedColors.length > 0) {
      //   this.colorList = namedColors.concat(this.colorList)
      // }
      // console.log(this.colorMap, this.colorKeys, this.colorList)
      // 当前value是一个预定义颜色的名称,而非一个16进制颜色字符串
      // 比如value = 'ByLayer'
      // console.log('传入颜色value:', this.value, this.namedColorMap)
      if (this.namedColorMap.hasOwnProperty(this.value)) {
        const key = this.value
        // 初始化select组件的value
        this.selectKey = key
        // 初始化color-picker组件的value
        this.pickColor = this.getColor(key)
      } else {
        // 当前value是一个16进制颜色字符串,比如value='#FF0000'
        // 更新select组件
        this.updateSelect(this.value)
      }
    },
    // 更新颜色相关数据(colorMap、colorKeys、colors等, 当用户点击color-picker选择颜色后调用)
    updateData(color) {
      // console.log('updateData:', color)
      // 该颜色不存在,新增一个
      if (!this.colorKeys.hasOwnProperty(color)) {
        const key = color
        // vue更新object对象
        // https://segmentfault.com/a/1190000009789481#articleHeader3
        // this.$set(this.colorMap, key, {
        //   color: color,
        //   label: '颜色' + color
        // })
        this.colorMap[key] = {
          color: color,
          label: '颜色' + color
        }
        this.colorList.push(key)
        // vue更新object对象
        // https://segmentfault.com/a/1190000009789481#articleHeader3
        // this.$set(this.colorKeys, color, key)
        this.colorKeys[color] = key
      }
    },
    // 更新select组件(用户点击color-picker选择颜色后调用)
    updateSelect(color) {
      // console.log('updateSelect:', color)
      // 16进制颜色字符串转换为大写
      const _color = color.toUpperCase()
      // 纯白色看不见,hack为whitesmoke颜色
      // if (_color === '#FFFFFF') _color = '#F5F5F5'
      // 更新颜色相关数据(colorMap、colorKeys、colors等)
      this.updateData(_color)
      // 更新下拉框的value -> this.selectKey
      const key = this.colorKeys[_color]
      this.selectKey = key
      // 更新color-picker组件的value -> this.pickColor
      this.pickColor = this.getColor(key)
      // console.log('updateSelect:', this.selectKey)
    },
    // color-picker组件change事件
    onColorPickerChange(color) {
      // console.log('onColorPickerChange：', color)
      // 更新下拉框
      this.updateSelect(color)
      // 给父组件发送消息
      this.$emit('change', color)
    },
    // select组件change事件
    onChange(key) {
      // console.log('color.vue onChange:', key)
      // 更新color-picker组件的value
      this.pickColor = this.getColor(key)
      // 如果key=ByLayer或ByBlock,则直接返回key
      if (this.namedColorMap.hasOwnProperty(key)) {
        this.$emit('change', key)
      } else {
        // 如果key=white/red/green等,则返回16进制字符串的值
        // 更新color-picker组件的value
        // 组件内部对白色进行hack(#FFFFFF --> #F5F5F5),需要恢复过来!
        const color = this.getColor(key)
        // if (color === '#F5F5F5') color = '#FFFFFF'
        this.$emit('change', color)
      }
    },
    blur() {
      // 使 input 失去焦点，并隐藏下拉框
      this.$refs.colors.blur()
    }
  }
}
</script>

<style lang='scss'>
.color-select {
  display: inline-block;
  .el-color-picker__trigger {
    height: 20px !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    border-width: 0 !important;
  }
}
</style>
